package cn.seaboot.flake.reverse;

import cn.seaboot.commons.core.CommonUtils;
import cn.seaboot.commons.core.SmartText;
import cn.seaboot.commons.core.StringUtils;
import cn.seaboot.flake.entity.MappingColumn;
import cn.seaboot.flake.entity.MappingTable;
import cn.seaboot.flake.entity.NormColumn;
import cn.seaboot.flake.entity.NormTable;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;

/**
 * 标注参数转数据映射模型
 *
 * @author Mr.css
 * @version 2020-12-04 9:54
 */
public class NormToMappingConverter {

    /**
     * JDBC 类型转换
     */
    private Function<NormColumn, String> converter = new JdbcTypeConverter();

    public Function<NormColumn, String> getConverter() {
        return converter;
    }

    public void setConverter(Function<NormColumn, String> converter) {
        this.converter = converter;
    }

    /**
     * 根据库表中的标准数据创建映射数据
     *
     * @param dataTables 数据库名
     * @return 表映射数据
     */
    public List<MappingTable> normTableToMappingTables(List<NormTable> dataTables) {
        if (CommonUtils.isNotEmpty(dataTables)) {
            List<MappingTable> res = new ArrayList<>(dataTables.size());
            for (int i = 0; i < dataTables.size(); i++) {
                NormTable dataTable = dataTables.get(i);
                MappingTable mappingTable = this.normTableToMappingTable(dataTable);
                mappingTable.setTableAlias("T" + SmartText.fillZero(i, 3));
                res.add(mappingTable);
            }
            return res;
        }
        return null;
    }

    /**
     * 根据库表中的标准数据创建映射数据
     *
     * @param normTable 数据库名
     * @return 表映射数据
     */
    public MappingTable normTableToMappingTable(NormTable normTable) {
        MappingTable mappingTable = this.convert2MappingTable(normTable);
        List<NormColumn> columns = normTable.getColumns();
        if (columns != null) {
            mappingTable.setColumns(this.convert2MappingColumns(columns));
        }
        return mappingTable;
    }

    /**
     * 标准基数据 -> 映射数据
     *
     * @param column DbNormColumn
     * @return DbMappingColumn
     */
    private MappingColumn convert2MappingColumn(NormColumn column) {
        MappingColumn col = new MappingColumn();
        col.setSchemaName(column.getSchemaName());
        col.setTableName(column.getTableName());

        // 字段名转换
        String columnName = column.getColumnName();
        col.setColumnName(columnName);
        col.setcamelName(StringUtils.underlineToCamel(columnName));
        col.setpascalName(StringUtils.underlineToPascal(columnName));

        // 字段类型
        col.setJavaType(converter.apply(column));
        col.setJdbcType(column.getJdbcType());
        col.setColumnType(column.getColumnType());

        // 中文注释/排序
        col.setColumnComment(column.getColumnComment());
        col.setOrdinalPosition(column.getOrdinalPosition());

        // 数字
        col.setNumericScale(column.getNumericScale());
        col.setNumericPrecision(column.getNumericPrecision());

        // 关键字

        // 字符串
        col.setLength(column.getLength());

        // 字段是否必要
        col.setDefaultValue(column.getDefaultValue());
        col.setNullable(column.getNullable());
        col.setRequire(column.getRequire());
        return col;
    }

    /**
     * 标准基数据 -> 映射数据
     *
     * @param columns DbNormColumn
     * @return DbMappingColumn
     */
    private List<MappingColumn> convert2MappingColumns(Collection<NormColumn> columns) {
        List<MappingColumn> res = new ArrayList<>();
        for (NormColumn column : columns) {
            MappingColumn col = this.convert2MappingColumn(column);
            res.add(col);
        }
        return res;
    }

    /**
     * 标准基数据 -> 映射数据
     *
     * @param table DbNormTable
     * @return DbMappingTable
     */
    private MappingTable convert2MappingTable(NormTable table) {
        MappingTable res = new MappingTable();
        res.setSchemaName(table.getSchemaName());
        res.setTableName(table.getTableName());
        res.setTableComment(table.getTableComment());
        // 截断开头的t
        String tableName = table.getTableName();
        if (tableName.startsWith("T_") || tableName.startsWith("t_")) {
            tableName = tableName.substring(2);
        }

        res.setCamelName(StringUtils.underlineToCamel(tableName));
        res.setPascalName(StringUtils.underlineToPascal(tableName));
        return res;
    }
}
